package com.hnu.scw.activiti;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.junit.Test;

import java.io.InputStream;
import java.util.List;
import java.util.zip.ZipInputStream;

/**
 * @author scw
 * @create 2018-01-15 11:04
 * @desc 用于进行演示Activiti的首例程序，即描述如何在代码中实现学生进行请假申请，班主任审核，教务处审核
 **/
public class ActivitiTest {
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    /**
     * 1、部署流程
     * 2、启动流程实例
     * 3、请假人发出请假申请
     * 4、班主任查看任务
     * 5、班主任审批
     * 6、最终的boss审批
     */
    /**
     * 1：部署一个Activiti流程
     * 运行成功后，查看之前的数据库表，就会发现多了很多内容
     * act_re_procdef   表多了一行请假申请数据，对应的start吧
     * shenqing:1:4	1	http://www.activiti.org/test	shenqing	shenqing	1	1	shenqing.bpmn	shenqing.png		0	1
     * act_get_bytearray多了2行数据，对应的，这2行数据都非常多，里面存了xml工作流，
     *
     * act_ru_task没有数据，
     * 测试中的大毛，小毛，可以做成外键，只要有相关身份的人就可以审批。
     * act_re_deploment有请假流程
     * 1	请假流程		2018-11-29 23:55:29
     */
    @Test
    public void creatActivitiTask(){
        //加载的那两个内容就是我们之前已经弄好的基础内容哦。
        //得到了流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        Deployment deploment = processEngine.getRepositoryService()
                .createDeployment()
                .name("请假流程")
                .addClasspathResource("shenqing.bpmn")
                .addClasspathResource("shenqing.png")
                .deploy();//完成部署 name流程名称，加载资源
        System.out.println(deploment.getId()+deploment.getName());//501,请假流程
    }

    /**通过zip加载*/
    @Test
    public void creatActivitiTaskByZip(){
        //加载的那两个内容就是我们之前已经弄好的基础内容哦。
        //得到了流程引擎
        InputStream in = this.getClass().getClassLoader().getResourceAsStream("shenqing.zip");
        ZipInputStream zipInputStream = new ZipInputStream(in);
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        Deployment deploment = processEngine.getRepositoryService()
                .createDeployment()
                .name("请假流程")
                .addZipInputStream(zipInputStream)//通过zip加载流程
                .deploy();//完成部署 name流程名称，加载资源
        System.out.println(deploment.getId()+deploment.getName());//501,请假流程
    }



    /**
     * 2：启动流程实例
     * act_re_procdef没变化啊
     * shenqing:1:4	1	http://www.activiti.org/test	shenqing	shenqing	1	1	shenqing.bpmn	shenqing.png		0	1
     * shenqing:1:4	1	http://www.activiti.org/test	shenqing	shenqing	1	1	shenqing.bpmn	shenqing.png		0	1
     * act_ru_task多了一行数据
     * 104	1	101	101	shenqing:1:4	请假申请			请假申请				50	2018-11-29 23:36:33		1
     *
     *
     * act_hi_actinst有2行数据，有104
     * 102	shenqing:1:4	101	101	_2			StartEvent	startEvent		2018-11-29 23:57:00	2018-11-29 23:57:00	5
     * 103	shenqing:1:4	101	101	请假申请	104		请假申请	userTask		2018-11-29 23:57:00
     * act_hi_procinst
     *  101	101		shenqing:1:4	2018-11-29 23:57:00				_2
     *
     *  act_hi_taskinst
     *  104	shenqing:1:4	请假申请	101	101	请假申请					2018-11-29 23:57:00					50
     *  act_ru_execution
     *  101	1	101			shenqing:1:4		请假申请	1	0	1	0	1	2
     *
     */
    @Test
    public void testStartProcessInstance(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        processEngine.getRuntimeService()
                .startProcessInstanceById("shenqing:1:4");  //这个是查看数据库中act_ru_task表
    }

    /**部署流程2*/
    @Test
    public void testStartProcessInstance2(){
        String key="shenqing";//no processes deployed with key '请假流程',这里的key是act_re_procdef中的name
        ProcessInstance pi = processEngine.getRuntimeService().startProcessInstanceByKey(key);//使用定义的key启动流程
        System.out.println(pi.getId()//流程定义id
                +","+pi.getProcessInstanceId()//流程实例id
                +","+pi.getBusinessKey()+pi.toString());
    }
    /**Activiti支持消息启动事件和中间消息事件*/
    @Test
    public void testStartProcessInstance3(){
        String message="请假流程";
        ProcessInstance pi = processEngine.getRuntimeService().startProcessInstanceByMessage(message);
        System.out.println(pi.getId()//流程定义id
                +","+pi.getProcessInstanceId()//流程实例id
                +","+pi.getBusinessKey()+pi.toString());
    }

    /**
     * 完成请假申请
     * shenqing:1:4	1	http://www.activiti.org/test	shenqing	shenqing	1	1	shenqing.bpmn	shenqing.png		0	1
     *
     * act_ru_task数据变化
     * 202	1	101	101	shenqing:1:4	班主任			班主任		小毛		50	2018-11-29 23:37:56		1
     */
    @Test
    public void testQingjia(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        processEngine.getTaskService()
                .complete("104"); //查看act_ru_task表，为什么id是104，而且改成202都是固定的？
    }

    /**
     * 小明学习的班主任小毛查询当前正在执行任务
     * act_hi_actinst 加了一行数据，小毛，班主任执行任务
     *      *                              ACT_ID_   TSAK_ID  ACT_NAME             ASSIGNEE_
     *      * 102	shenqing:1:4	101	101	_2			    StartEvent	startEvent		2018-11-29 23:57:00	2018-11-29 23:57:00	5
     *      * 103	shenqing:1:4	101	101	请假申请	    104		请假申请	userTask		2018-11-29 23:57:00	2018-11-30 00:12:08	908231
     *      * 201	shenqing:1:4	101	101	班主任	    202		班主任	userTask	小毛	2018-11-30 00:12:08
     *      *
     *      *
     *      * act_hi_taskinst  数据多了班主任执行
     *      * 104	shenqing:1:4	请假申请	101	101	请假申请					2018-11-29 23:57:00		2018-11-30 00:12:08	908196	completed	50
     *      * 202	shenqing:1:4	班主任	101	101	班主任				小毛	2018-11-30 00:12:08					50
     */
    /**
     * 别人三个框对应三个人，张三，李四，王五，分别查询任务，
     * 这个三个框，就2个人，104得自己找。
     * */
    @Test
    public void testQueryTask(){
        //下面代码中的小毛，就是我们之前设计那个流程图中添加的班主任内容
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        List<Task> tasks = processEngine.getTaskService()//正在执行任务管理的相关service
                .createTaskQuery()//创建任务查询对象 大毛 id:402 name:教务处Task[id=402, name=教务处]
                .taskAssignee("大毛")//个人任务查询，小毛，  id:302 name:班主任Task[id=302, name=班主任]
                .list();
        for (Task task : tasks) {
            System.out.println("id:"+task.getId()+" name:"+task.getName()+task.toString());//输出act_ru_task的班主任
        }
    }

    /**
     * act_ru_task 班主任小毛完成任务
     * 202	1	101	101	shenqing:1:4	班主任			班主任		小毛		50	2018-11-29 23:37:56		1
     * act_ru_task 数据变为
     * 302	1	101	101	shenqing:1:4	教务处			教务处		大毛		50	2018-11-29 23:40:55		1
     *
     *  act_hi_actinst 加了一行教务处的数据
     * 102	shenqing:1:4	101	101	_2			StartEvent	startEvent		2018-11-29 23:57:00	2018-11-29 23:57:00	5
     * 103	shenqing:1:4	101	101	请假申请	104		请假申请	userTask		2018-11-29 23:57:00	2018-11-30 00:12:08	908231
     * 201	shenqing:1:4	101	101	班主任	202		班主任	userTask	小毛	2018-11-30 00:12:08	2018-11-30 00:21:51	583859
     * 301	shenqing:1:4	101	101	教务处	302		教务处	userTask	大毛	2018-11-30 00:21:51
     *
     * act_hi_taskinst  数据多了教务处的
     * 104	shenqing:1:4	请假申请	101	101	请假申请					2018-11-29 23:57:00		2018-11-30 00:12:08	908196	completed	50
     * 202	shenqing:1:4	班主任	101	101	班主任				小毛	2018-11-30 00:12:08		2018-11-30 00:21:51	583826	completed	50
     * 302	shenqing:1:4	教务处	101	101	教务处				大毛	2018-11-30 00:21:51					50
     *
     *  act_ge_property
     * next.dbid	401	5
     * schema.history	create(5.13)	1
     * schema.version	5.13	1
     */
    @Test
    public void testFinishTask_manager(){
        ProcessEngine engine = ProcessEngines.getDefaultProcessEngine();
        engine.getTaskService()
                .complete("302"); //查看act_ru_task数据表  上面的小毛的302
    }

    /**
     * 教务处的大毛完成的任务
     * shenqing:1:4	1	http://www.activiti.org/test	shenqing	shenqing	1	1	shenqing.bpmn	shenqing.png		0	1
     *
     * act_ru_task 没有数据了
     * act_ge_property的数据便了，从201变成301，
     * act_ru_execution一行数据没了
     *
     *  act_hi_actinst
     * 102	shenqing:1:4	101	101	_2			StartEvent	startEvent		2018-11-29 23:57:00	2018-11-29 23:57:00	5
     * 103	shenqing:1:4	101	101	请假申请	104		请假申请	userTask		2018-11-29 23:57:00	2018-11-30 00:12:08	908231
     * 201	shenqing:1:4	101	101	班主任	202		班主任	userTask	小毛	2018-11-30 00:12:08	2018-11-30 00:21:51	583859
     * 301	shenqing:1:4	101	101	教务处	302		教务处	userTask	大毛	2018-11-30 00:21:51	2018-11-30 00:24:38	167333
     * 401	shenqing:1:4	101	101	_3			EndEvent	endEvent		2018-11-30 00:24:38	2018-11-30 00:24:38	0
     *
     * act_hi_taskinst
     * 104	shenqing:1:4	请假申请	101	101	请假申请					2018-11-29 23:57:00		2018-11-30 00:12:08	908196	completed	50
     * 202	shenqing:1:4	班主任	101	101	班主任				小毛	2018-11-30 00:12:08		2018-11-30 00:21:51	583826	completed	50
     * 302	shenqing:1:4	教务处	101	101	教务处				大毛	2018-11-30 00:21:51		2018-11-30 00:24:38	167297	completed	50
     *
     * act_ge_property
     * next.dbid	501	6
     * schema.history	create(5.13)	1
     * schema.version	5.13	1
     */
    @Test
    public void testFinishTask_Boss(){
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        processEngine.getTaskService()
                .complete("402");  //查看act_ru_task数据表，大毛任务id是402
    }

    /**查询流程定义*/
    @Test
    public void  findProcess(){
        List<ProcessDefinition> list = processEngine.getRepositoryService().
                createProcessDefinitionQuery()//创建流程定义查询
                //.deploymentId("");//根据部署对象id查
                //.processDefinitionId("");//根据流程定义id查询
                //.processDefinitionKey("");//根据流程定义Key查询
                .orderByProcessDefinitionVersion().asc().//按版本升序排序
                        list();//返回一个结果集
        for (ProcessDefinition p:
             list) {//shenqing:1:4shenqing1null
            System.out.println(p.getId()+p.getName()+p.getDeploymentId()+p.getDescription()
                            + p.getResourceName()//资源文件
                             +p.getVersion()//流程定义版本号
            );
            System.out.println(p.toString());//这个类没有重写toString(),= = ,要一个个的输出
        }
    }



    /**
     *不带级联的删除，删除流程定义，只能删除没有启动的流程，如果流程启动，就会抛出异常
     *
     * */
    @Test
    public void deleteProcessDefine(){
        String id= "";
        processEngine.getRepositoryService().deleteDeployment(id);//不是级联删除
        processEngine.getRepositoryService().deleteDeployment(id,true);//级联删除

    }


    /**
     * 历史活动查询
     */
    @Test
    public void historyActInstanceList(){
        List<HistoricActivityInstance>  list=processEngine.getHistoryService() // 历史相关Service
                .createHistoricActivityInstanceQuery() // 创建历史活动实例查询
                .processInstanceId("2501") // 执行流程实例id
                .finished()
                .list();
        for(HistoricActivityInstance hai:list){
            System.out.println("活动ID:"+hai.getId());
            System.out.println("流程实例ID:"+hai.getProcessInstanceId());
            System.out.println("活动名称："+hai.getActivityName());
            System.out.println("办理人："+hai.getAssignee());
            System.out.println("开始时间："+hai.getStartTime());
            System.out.println("结束时间："+hai.getEndTime());
            System.out.println("=================================");
        }
    }




}
